What follows is a detailed description of how Lua is modified to get the ease and compatibility intended for tool-building. If you want to start building tools with Lua as provided here, examine the example scripts to see how it's done. They emphasise a way of writing Lua that uses the most enduring methods, so they should be more likely to stay working even if Lua changes. (It often does!)

The remaining text here will only be important if you want to avoid unwanted library code or to modify its C source files. A few modifications and extensions were made in Lua's C API, partly to make the function calls writeable in exactly the same way for all three versions used in LuaTools, and partly to make it easier for new Lua and C code to know the context in which the code was being run.

LuaTools is designed to make dedicated tools, as easily as possible. Commandline tools or simple programs whose only interface is a file dialog are equally easy to make. More complex Windows GUI programs are possible, but at that point it is probably best to write them with systems like wxLua that have better support for doing it. This system is designed to make a small tool at times when the alternative seems to be some unknown multi-megabyte download! At times like those, writing a tool should be easier. The aim of this system is to make it so. It is intended for use in Windows, but the methods were designed to be modular, so it may be easy to replace some modules with equivalents that run on Linux and BSD.

A specific case is the pair of functions PutConsole() and GetConsole(), which are tested in several compilers, GCC, TCC, and Watcom, the latter case using supporting functions written in 'x86' ASM, instead of the Win32 API functions that support them here. Those two main functions solve several problems with using a console based on x86 systems, and they should not be rewritten in any way, not one byte! The trick is to do what it takes to replace the functions they depend on, to make them work in another system. This precise division of labour is important, it is an example of how LuaTools was designed to bridge otherwise incompatible systems to make a system that can be expected to work, and stay working even if other things change.

When making this system, it was found that making function libraries integral to Lua like its own standard libraries was the best way to make new ones intended to replace any of those that are not needed. Excluding unwanted libraries is a good way to reduce compiled file sizes, e.g. if writing a format converter or text parser, it may be easy to use string functions and avoid all the other libraries while adding a tiny library to load and save binary files, or if wanting to use coloured text on older Windows system console windows, the supplied console library will be of more use than the 'io' library if basic text display is the main IO requirement.

ALL SELECTIONS TO ENABLE LUA LIBRARIES ARE DONE IN LUALIB.H, there is no 'linit.c', and there is no requirement to 'require', and no 'loadlib' or 'package' details to consider. If required functions exist only in compiled DLL's, they can still be used if these versions of Lua are compiled with DEF files based on the relevant DLL's. For example, the supplied console library can call the MessageBox function in USER32.DLL, which is useful as a diagnostic tool or warning method when a command window must be unchanged. Compiling Lua code this way, using TCC, gives the most complete control possible, so handling of external libraries by Lua script is pointless when constructing dedicated tools that use fixed and specialised requirements. Some things, like string parsing and file format conversion, are more easily done in Lua, and others, like printing coloured text to a command prompt window in Windows 98, are impossible without C code using the Win32 API, and a hybrid system makes it easier to do both in a single program.

Lua functions often used in libraries are reduced to luaL_checkstring, luaL_optstring, luaL_checkint, luaL_checknumber. The 'length' variants luaL_checklstring, luaL_optlstring don't exist. The standard variants replace them, so there is an extra NULL argument to luaL_checkstring and luaL_optstring, to be replaced by the address of a Size_t variable if the size is wanted. Lua v4's equivalents have been renamed to fit the convention above so a new library written with these functions will work the same way in any of the three supplied Lua versions.

Lua v4 now has some Lua v5 compatibility for function calls like table.insert instead of tinsert, so a script needs much less editing if ported to Lua v4 after writing for Lua v5. The debug library is NOT changed because there are too many differences. Use Lua 4 calls, or nothing. The string library supports all but string.gfind. The maths library supports all Lua 4 calls with their Lua 5 equivalents but does not add any new functions other than 'mod' to allow all versions to use the '%' mod operator, for consistent scripting (but it is likely that the a.div() function in the '#aux.c' library will be even more helpful!) The table functions are similarly supported (as part of lbaselib.c), with table.concat added. Coroutine calls have no equivalents in Lua 4 so are not added. Some OS calls are supported (as part of liolib.c). The 'io' calls are problematic. See notes in liolib.c for details.

A set of string functions is added to 'lauxlib.c' to support new C library code. They are designed to be fast, to use pointers and dereferencing the way ASM uses the SI and DI registers, and to take string length limits for safety, and to ALWAYS terminate any C string they make with a terminator, so ALWAYS consider the space for it in any length given. This practise was learned from Theo De Raadt's 'strlcat' and 'strlcpy', when making the first of these to be created, Str_C, intended to combine the purposes of the two originals. The aim of these functions is to make C string handling easy and safe, with a minimal set of functions that enable some powerful work to be done with them. Have at it... Two of them convert integers to numeral strings and vice versa, which is useful in small statically linked programs where the 16KB or so used by printf() or scanf() is not wanted, or when you want a base 2 numeral, which is not available in some standard functions. The a.int() function is especially useful when you want a default number base for numeric entry while also allowing a user to override it with a known number in another standard number base if it's more convenient.

The file 'lua.h' has integers INTERACTIVE_MODE and NO_ERROR_REPORTS as flags, with function prototypes NoScript() and NoErrors() declared for their use. The file 'lstate.c' holds these functions, just after the last 'include' statement. Passing a 0 or a 1 to either function is done in the top level C file, i.e. 'Lua.c' or a C file made from a script by Luac. This works whether the top level program is built separately, or with a Lua DLL. When writing new code libraries, it may be important to know these states, which is why the flags are global. Lua.c does detect interactive mode, but the standard distributions had no way to pass this awareness to other files because argc and argv were kept strictly local to the top level file. Detecting the state of the Lua 'arg' array might have worked, but this would not have been a practical method for a new code library written in C code!

Printing error messages in Lua v4 is done by the line in 'lstate.c' that uses fprintf to stderr. Lua 5 uses 'lauxlib.c'. All Lua versions were designed as an extension language in a host C-based program, so an external error message handler can be defined, and whether or not this is defined, there are stack-related details in later versions that must not be interrupted. All that NO_ERROR_REPORTS and NoErrors() will do is determine whether or not the inbuilt error printer function actually writes to 'stderr'. Code libraries may print directly there, but most of those are omitted in programs designed to be as small as possible. The default state is to print error messages, but in LUAC-based EXE files, it may be better to eliminate Lua error reporting, in which case the main C file should call NoErrors(1), and errors should be handled directly, as if a pure C program were being written. Note that Lua errors will likely cause the EXE file to quit, whether errors are printed or not, so take care what is done in Lua code, especially if excluding any of the standard libraries!

One obvious cause of error is calling a function like 'print' if the base library is excluded. In this case, use the console library to print text. It's smaller, and can do it in colour. The string library 'lstrlib.c' is the one standard library always worth including, because the 'gsub' and 'find' functions are extremely powerful. If patterns are used to eliminate text inputs that cannot be numbers, there is no need to test the type, or use 'tonumber' to force the string to be a number. Simple coercion can be used, like string+0, avoiding the need to call 'tonumber' which is likely to be in an excluded library, and calling it would cause an error. Coercion is considered riskier than 'tonumber' but it need not be if the string library or the Lua API test functions are used carefully to prevent bad data arising before a coercion is attempted. All library functions should contain calls to Lua error-checking functions, so this security is there to be used. If you want to avoid Lua's error reports and replace them with your own, Lua's API lets you do that too.
